package com.lance.shiro.web;

import com.google.common.base.Throwables;
import com.lance.shiro.entity.IUser;
import com.lance.shiro.service.GenericCrudService;
import com.lance.shiro.utils.RequestUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@RestController
public abstract class BaseController<T> {
    public Logger log = LogManager.getLogger(getClass());
    private GenericCrudService<T> service;

    public BaseController(GenericCrudService<T> service){
        this.service = service;
    }

    //findAll
    @RequestMapping
    public ResponseEntity listAll() {
        return  RequestUtils.success("success",this.service.fetchAll());
    }

    //findByint
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public  ResponseEntity get(@PathVariable int id) {
        return RequestUtils.success("success", this.service.fetchById(id));
    }



    //insert
    @RequestMapping(method=RequestMethod.POST, consumes={MediaType.APPLICATION_JSON_VALUE})
    public  ResponseEntity create(@RequestBody T json) {
        log.debug("create() with body {} of type {}", json, json.getClass());
        T ret = this.service.insert(json);
        return RequestUtils.success("Operation success!", ret);
    }

    //update
    @RequestMapping(value="/{id}", method=RequestMethod.POST, consumes={MediaType.APPLICATION_JSON_VALUE})
    public  ResponseEntity update(@PathVariable int id, @RequestBody T json) {
        log.debug("update() of id#{} with body {}", id, json);
        log.debug("T json is of type {}", json.getClass());

        T entity = this.service.fetchById(id);
        try {
            BeanUtils.copyProperties(entity, json);
        }
        catch (Exception e) {
            log.warn("while copying properties", e);
            throw Throwables.propagate(e);
        }
        int affectedRow = this.service.update(entity);
        log.debug("affect row {}, updated enitity: {}",affectedRow, entity);
        return RequestUtils.success("updated enitity",entity);

    }

    //delete
    @RequestMapping(value="", method=RequestMethod.DELETE)
    public  ResponseEntity delete(@RequestParam(name = "id", required = false) List<Integer> ids) {
        int expectRowAffected = ids.size();
        int actualRowAffected = 0;
        for (int id : ids) {
            actualRowAffected += this.service.delete(id);
        }
        if(actualRowAffected == expectRowAffected){
            return RequestUtils.success("Operation success!", ids);
        }else{
            return RequestUtils.error("Operation failed!Delete rows {}", actualRowAffected);
        }

    }
}
